﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WingApp
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            textBox2.Text = "LFCF";
            textBox4.Text = " ";
            //MasterKey选择器中的值。
            MasterKeySelect.Items.Add("6b9d086f647a4ebda12abf6fb79eab8d");
            MasterKeySelect.Items.Add("7d8fa8af1e44469e88eb3486a10db310");
            MasterKeySelect.SelectedIndex = -1;//这里如果不设置为-1，在选择联动时会报错。
            //productId选择器中的值
            productIdSelect.Items.Add("10042763");
            productIdSelect.Items.Add("10043842");
            productIdSelect.SelectedIndex = 0;//设置默认值为第一个
            //Paen选择器中的值
            PaenSelect.Items.Add("000000");
            PaenSelect.Items.Add("110000");
            PaenSelect.SelectedIndex = 0;//设置默认值为第一个
        }
        public class All//定义全局变量
        {
            public static string sbstring;//需要编码的字符串
            public static string enstring;
            public static string bodystring;
        }
        //post下发命令
        private void button1_Click(object sender, EventArgs e)
        {
            httpPostCommand();
        }
        //添加上传时间
        private void Timesetting_Items_Add_Click(object sender, EventArgs e)
        {
            if (Updatatimesetting_Result.Items.Count < 24)
            { 
                //获取时刻设定的时间值
                string Timesetting_result = Timesetting.Value.ToString("HH:mm");

                Updatatimesetting_Result.Items.Add(Timesetting_result);
            }
            else
            {
                MessageBox.Show("上传时间最多24组，已达上限！", "添加出错", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        //删除上传时间
        private void Timesetting_Items_Delete_Click(object sender, EventArgs e)
        {
            if (Updatatimesetting_Result.Items.Count > 0)
            {
                if (Updatatimesetting_Result.SelectedItems.Count == 0)
                {
                    Updatatimesetting_Result.Items.RemoveAt(Updatatimesetting_Result.Items.Count - 1);
                }
                else
                {
                    for (int i = Updatatimesetting_Result.Items.Count - 1; i >= 0; i--)
                    {
                        Updatatimesetting_Result.Items.Remove(Updatatimesetting_Result.SelectedItem);
                    }
                }
            }
            else
            {
                MessageBox.Show("更新时间设置结果框已为空！", "删除出错", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        
        //post命令下发方法
        public void httpPostCommand()
        {
            long ofs = TimeOffset();
            long timestamp = DateTimeHelper.CurrentUnixTimeMillis() + ofs;//获取时间偏移量
            string tstamp = timestamp.ToString();
            string productId = productIdSelect.SelectedItem.ToString();
            string MasterKey = MasterKeySelect.SelectedItem.ToString();
            string deviceId = textBox1.Text;
            string deviceGroupId = textBox3.Text;
            string application = "3vFOmedXVs3";
            string secret = "jyMQuyN63o";
            string userName = textBox2.Text;
            //生成PAEN命令部分的字符串
            string PaenString = "\"PAEN\":\"" + PaenSelect.SelectedItem.ToString() + "\"";
            //生成USER命令部分的字符串
            string UserString = "\"USER\":\"" + textBox4.Text + "\"";
            #region //生成Tmr命令部分的字符串
            //将Updatatimesetting_Result中的值放入数组中。
            ArrayList Updatatimesetting_result_items = new ArrayList();
            for (int i = 0; i < Updatatimesetting_Result.Items.Count; i++)
            {
                Updatatimesetting_result_items.Add(Updatatimesetting_Result.Items[i].ToString());
            }
            //Arraylist排序，保证时间按照从小到大顺序排列
            Updatatimesetting_result_items.Sort();                    
            //生成所需字符串
            StringBuilder BuffCmd_Timesetting_UpT = new StringBuilder("[");

            for (int i = 0; i < Updatatimesetting_Result.Items.Count; i++)
            {
                if (i == Updatatimesetting_result_items.Count - 1)
                {
                    BuffCmd_Timesetting_UpT.Append("\"");
                    BuffCmd_Timesetting_UpT.Append(Updatatimesetting_result_items[i].ToString());
                    BuffCmd_Timesetting_UpT.Append("\"");
                }
                else
                {
                    BuffCmd_Timesetting_UpT.Append("\"");
                    BuffCmd_Timesetting_UpT.Append(Updatatimesetting_result_items[i].ToString());
                    BuffCmd_Timesetting_UpT.Append("\",");
                }
            }
            BuffCmd_Timesetting_UpT.Append("]");
            string TimeString = BuffCmd_Timesetting_UpT.ToString();
            //去掉时间中的冒号
            TimeString = TimeString.Replace(":", "");
            #endregion
            string TmrString = "\"TMR\":{\"mode\":\"20\",\"tm\":" + TimeString + "}";

            //将PaenString、UserString、TmrString字符串放入数组中
            ArrayList payloadArr = new ArrayList();
            if (PaenSelect.SelectedItem.ToString() != "")
            {
                payloadArr.Add(PaenString);
            }
            if (textBox4.Text != "")
            {
                payloadArr.Add(UserString);
            }
            if (Updatatimesetting_Result.Items.Count != 0)
            {
                payloadArr.Add(TmrString);
            }

            //将payloadArr中的元素用","分隔。生成最终payload。
            string payload = string.Join(",", payloadArr.ToArray(typeof(string)) as string[]);

            //string bodystring= "{\"deviceId\": \"432f5c3720aa4e17b7ed41e8d7d602e9\",\"operator\": \"guo\",\"productId\": 10043842,\"ttl\": 172800,\"content\": { \"payload\":{\"PAEN\":\"000000\",\"USER\":\"567890\",\"TMR\":{\"mode\":\"20\",\"tm\":[\"1730\",\"1830\",\"1930\"]}},\"dataType\":1}}";
            
            //判断指令级别是设备级还是群组级
            if (radioButton1.Checked == true)
            {
                All.bodystring = "{\"deviceId\":\"" + deviceId + "\",\"operator\":\"" + userName + "\",\"productId\":\"" + productId + "\",\"ttl\": 172800,\"content\":{\"payload\":{" + payload + "},\"dataType\":1}}";
            }
            else if(radioButton2.Checked == true)
            {
                All.bodystring = "{\"deviceGroupId\":\"" + deviceGroupId + "\",\"operator\":\"" + userName + "\",\"productId\":\"" + productId + "\",\"ttl\": 172800,\"level\": 3,\"content\":{\"payload\":{" + payload + "},\"dataType\":1}}";
            }

            byte[] body = Encoding.UTF8.GetBytes(All.bodystring);

            IDictionary<string, string> param = new Dictionary<string, string>();
            param["MasterKey"] = MasterKey;//将MasterKey加入参数。

            string url = "https://ag-api.ctwing.cn/aep_device_command/command";//不同请求有不同的url
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "POST";
            //SetHeaderValue(request.Headers, "Content-Type", "application/json");//设备API地址和 首部参数
            SetHeaderValue(request.Headers, "MasterKey", MasterKey);//有的需要有的不需要
            SetHeaderValue(request.Headers, "application", application);
            SetHeaderValue(request.Headers, "sdk", "0");
            SetHeaderValue(request.Headers, "version", "20190712225145");//不同版本号
            SetHeaderValue(request.Headers, "signature", SignPost(param, timestamp, application, secret, body));
            SetHeaderValue(request.Headers, "timestamp", tstamp);
            //textBox2.Text = SignPost(param, timestamp, application, secret, body);//显示签名

            request.ProtocolVersion = new Version(1, 1);
            request.ContentLength = body.Length;
            using (Stream reqStream = request.GetRequestStream())
            {
                reqStream.Write(body, 0, body.Length);
                reqStream.Close();
            }
            HttpWebResponse resp = (HttpWebResponse)request.GetResponse();
            Stream stream = resp.GetResponseStream();
            //获取响应内容 
            using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
            {
                string readerStr = reader.ReadToEnd();//返回值
                JObject jsonReader = (JObject)JsonConvert.DeserializeObject(readerStr);
                if(radioButton1.Checked == true)
                {
                    textBox5.Text = jsonReader["result"]["commandStatus"].ToString();
                }
                else if (radioButton2.Checked == true)
                {
                    textBox5.Text = jsonReader["msg"].ToString();

                }
                //textBox5.Text = jsonReader.ToString();
            }
        }
        //计算时间偏移
        public static long TimeOffset()
        {
            string url = "https://ag-api.ctwing.cn/echo";
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "HEAD";
            request.AllowAutoRedirect = false;
            //服务器返回的同时获取本地时间
            long start = DateTimeHelper.CurrentUnixTimeMillis();//本地时间开始
            HttpWebResponse reponse = (HttpWebResponse)request.GetResponse();
            string serviceTime = reponse.GetResponseHeader("x-ag-timestamp");//服务器时间，响应报文头timestamp
            long end = DateTimeHelper.CurrentUnixTimeMillis();//本地时间结束
            long stime = long.Parse(serviceTime);
            long offset = stime - (start + end) / 2L;//时间偏移量
            return offset;
        }
        //计算本地时间需调用的方法
        internal static class DateTimeHelper
        {
            private static readonly System.DateTime Jan1st1970 = new System.DateTime(1970, 1, 1, 0, 0, 0, System.DateTimeKind.Utc);
            public static long CurrentUnixTimeMillis()
            {
                return (long)(System.DateTime.UtcNow - Jan1st1970).TotalMilliseconds;
            }
        }
        //以下为生成post签名方法
        public static string SignPost(IDictionary<string, string> param, long timestamp, string application, string secret, byte[] body)
        {
            // 连接系统参数
            StringBuilder sb = new StringBuilder();
            sb.Append("application").Append(":").Append(application).Append("\n");
            sb.Append("timestamp").Append(":").Append(timestamp).Append("\n");

            //连接请求参数,例如MasterKey。
            if (param != null)
            {
                SortedSet<string> keys = new SortedSet<string>(param.Keys);
                IEnumerator<string> i = keys.GetEnumerator();
                while (i.MoveNext())
                {
                    string s = i.Current;
                    string val = param[s];
                    sb.Append(s).Append(":").Append(string.ReferenceEquals(val, null) ? "" : val).Append("\n");
                }
            }
            //body数据写入需要签名的字符流中
            MemoryStream baos = new MemoryStream();
            byte[] Esb = Encoding.UTF8.GetBytes(sb.ToString());
            baos.Write(Esb, 0, Esb.Length);
            if (body != null && body.Length > 0)
            {
                baos.Write(body, 0, body.Length);
                byte[] Enbody = Encoding.UTF8.GetBytes("\n");
                baos.Write(Enbody, 0, Enbody.Length);
            }
            // 得到需要签名的字符串
            byte[] b = baos.ToArray();
            string @string = Encoding.UTF8.GetString(b, 0, b.Length);
            All.sbstring = @string;
            Console.WriteLine("sign string: " + @string);

            //HMAC-SHA1加密

            HMACSHA1 hmacsha1 = new HMACSHA1();
            hmacsha1.Key = Encoding.UTF8.GetBytes(secret);
            byte[] dataBuffer = Encoding.UTF8.GetBytes(@string);
            byte[] hashBytes = hmacsha1.ComputeHash(dataBuffer);
            string encryptedString = Convert.ToBase64String(hashBytes);//base64编码
            All.enstring = encryptedString;
            return encryptedString;
        }
        // HTTP协议报文头加入
        public static void SetHeaderValue(WebHeaderCollection header, string name, string value)

        {
            var property = typeof(WebHeaderCollection).GetProperty("InnerCollection", BindingFlags.Instance | BindingFlags.NonPublic);
            if (property != null)
            {
                var collection = property.GetValue(header, null) as NameValueCollection;
                collection[name] = value;
            }
        }
        //MasterKeySelect与productIdSelect联动，如果第一个选择器的索引不设置为-1会报错。 
        private void productIdSelect_SelectedIndexChanged(object sender, EventArgs e)
        {
            MasterKeySelect.SelectedIndex = productIdSelect.SelectedIndex;
        }

        private void MasterKeySelect_SelectedIndexChanged(object sender, EventArgs e)
        {
            productIdSelect.SelectedIndex = MasterKeySelect.SelectedIndex;
        }
        //paen选择提示
        private void PaenSelect_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (PaenSelect.SelectedIndex == 0)
            {
                label9.Text = "仅上传数据";
            }
            else
            {
                label9.Text = "上传数据与配置参数";
            }
        }
    }
}
